package com.lw.security.security;

import com.lw.security.security.handler.MyFailHandler;
import com.lw.security.security.handler.MySuccessHandler;
import com.lw.security.security.service.MyUserSetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

/**
 * @author Administrator
 * @version 1.0
 * @description:
 * @date 2022/3/28 17:18
 */
@Component
@EnableWebSecurity//开启security
@EnableGlobalMethodSecurity(prePostEnabled = true,jsr250Enabled = true,proxyTargetClass = true)//开启注解进行权限判断
public class MyBaseSecurityConfig extends WebSecurityConfigurerAdapter {
    private MySuccessHandler mySuccessHandler;

    @Autowired
    public void setMySuccessHandler(MySuccessHandler mySuccessHandler) {
        this.mySuccessHandler = mySuccessHandler;
    }

    private MyFailHandler myFailHandler;

    @Autowired
    public void setMyFailHandler(MyFailHandler myFailHandler) {
        this.myFailHandler = myFailHandler;
    }

    private MyUserSetailService userSetailService;

    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    public void setbCryptPasswordEncoder(BCryptPasswordEncoder bCryptPasswordEncoder) {
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }

    @Autowired
    public void setUserSetailService(MyUserSetailService userSetailService) {
        this.userSetailService = userSetailService;
    }

    /**
     * 告诉security 我们当前登录的账号在数据库中密码以及编码格式，剩下的就是spring security进行操作
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userSetailService)//我们就知道了数据库中的密码
                .passwordEncoder(bCryptPasswordEncoder);//密码可能是MD5值，我们指定一个密码转换方式
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**","/css/**");//放行我们所有需要放行的地址
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //告诉security 我们页面传递过滤的数据，哪个是用户名，哪个是密码
        http.csrf().disable();
        http.authorizeRequests()//认证请求
                .and().formLogin()//security提供了一个默认的登录页面，默认地址就是/login，我们可以改
                //.disable()//禁用默认登录方式
                //.loginPage("/login.html")//自定义登录页面
                .loginProcessingUrl("/login")//自定义我们的登录处理地址,注意这个地址不需要我们写controller,我们只需要写路径就行, security会自动帮我们处理这个地址,所以这个地址不要和项目的地址重复
                //.usernameParameter("uName")//自定义用户名的参数，默认是username，如果是默认页面，可以忽略，写了也白写
                //.passwordParameter("pwd")//自定义密码的参数
                //.successForwardUrl("/success.html")//如果登陆成功自动转到什么页面
                //.failureForwardUrl("/fail.html")//默认失败是在登录页面并提示密码错误
                .successHandler(mySuccessHandler)//登录成功之后怎么做
                .failureHandler(myFailHandler)//登录失败之后怎么做
                .permitAll()//放行，登录地址不需要拦截
                .and().logout().logoutUrl("/logout")//自定义退出地址，这个地址不需要写，security会自动退出并清理数据
                .permitAll()
                .and().authorizeRequests().anyRequest()//任意地址，除了上面单独配置的地址
                .authenticated();//必须登录才行，取决于业务需求

    }
}
